package com.larson.creator.view
{
	import com.larson.creator.ApplicationFacade;
	import com.larson.creator.model.*;
	import com.larson.creator.model.vo.*;
	import com.larson.creator.view.components.*;
	import com.mapquest.*;
	import com.mapquest.tilemap.*;
	import com.mapquest.tilemap.controls.*;
	import com.mapquest.tilemap.overlays.*;
	import com.mapquest.tilemap.pois.*;
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import mx.events.ResizeEvent;
	import mx.collections.ArrayCollection;	
	import org.puremvc.as3.interfaces.*;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	public class buildMediator extends Mediator implements IMediator
	{
        // Cannonical name of the Mediator
        public static const NAME:String = "buildMediator";

		private var fileConvertProxy:FileConvertProxy;  
        private var rActive:Boolean = false;
		
		[Embed (source="/images/waypoint.png")]
		private var wpIcon:Class;
		
		[Embed (source="/images/waypoint.png")]
		private var wpCursor:Class;
		
		private var wpCollection:ShapeCollection;
		private var wpIndex:Number;
		private var activeCursor:int;
		private var defaultCursor:int;
		private var dragging:Boolean = false;
		private var routing:Boolean = false;
		private var exec:Exec;
		private var sessionId:String;
		        
        /**
         * Constructor. 
         */
		public function buildMediator (viewComponent:buildScreen)
		{
            // pass the viewComponent to the superclass where 
            // it will be stored in the inherited viewComponent property
            super( NAME, viewComponent );
            
            build.addEventListener(buildScreen.CREATE_BUILD_MAP, this.createMap);
            build.addEventListener(buildScreen.ENABLE_ROUTING, this.enableRouting);
            build.addEventListener(buildScreen.CLEAR_ROUTE, this.clearRoute);
            
			exec = new Exec("route.dev.mapquest.com", "mq", 80);
			exec.setClientId("79217");
			exec.setPassword("jJ7wN9uZ"); 
			
			exec.addEventListener(Exec.TRANS_TYPE_CREATE_SESSION, onSessionCreate);
			exec.createSessionEx(new MQSession());
			
			exec.addEventListener(Exec.TRANS_TYPE_DOROUTE, routeResults);
			exec.addEventListener(Exec.EVENT_DO_TRANSACTION_ERROR, routeError);           
		}
		
		private function onSessionCreate( evt:ExecResultEvent ):void {
			this.sessionId = SessionId(evt.resultData).toString();
		}
		
        /**
         * List all notifications this Mediator is interested in.
         * <P>
         * Automatically called by the framework when the mediator
         * is registered with the view.</P>
         * 
         * @return Array the list of Nofitication names
         */
        override public function listNotificationInterests():Array 
        {

            return [ 
					ApplicationFacade.LOADING_STEP,
					ApplicationFacade.LOADING_COMPLETE,
					ApplicationFacade.DATA_READY
					];
        }

        /**
         * Handle all notifications this Mediator is interested in.
         * <P>
         * Called by the framework when a notification is sent that
         * this mediator expressed an interest in when registered
         * (see <code>listNotificationInterests</code>.</P>
         * 
         * @param INotification a notification 
         */
        override public function handleNotification( note:INotification ):void 
        {
            switch ( note.getName() ) 
			{
				case ApplicationFacade.CONVERT_FILE_COMPLETE:
					break;
					
				case ApplicationFacade.LOADING_COMPLETE:
					break;
					
				case ApplicationFacade.DATA_READY:
					// Get the mapping data from the fileconversion proxy.
					// Get the convert data Proxy in order to acquire the data provider for our data grid.
					var fileLoadProxy:FileLoadProxy = ApplicationFacade.getFileLoadProxy();
					mapPoints(fileLoadProxy.rawData, fileLoadProxy.lineData);

					break;
            }
        }

        /**
         * Cast the viewComponent to its actual type.
         * 
         * <P>
         * This is a useful idiom for mediators. The
         * PureMVC Mediator class defines a viewComponent
         * property of type Object. </P>
         * 
         * <P>
         * Here, we cast the generic viewComponent to 
         * its actual type in a protected mode. This 
         * retains encapsulation, while allowing the instance
         * (and subclassed instance) access to a 
         * strongly typed reference with a meaningful
         * name.</P>
         * 
         * @return SplashScreen the viewComponent cast to org.puremvc.as3.demos.flex.appskeleton.view.components.SplashScreen
         */
		 
        protected function get build():buildScreen
		{
            return viewComponent as buildScreen;
        }

		public function createMap(event:Event=null):void {
			
			wpIndex = 0;
			wpCollection = new ShapeCollection("waypoints");
			var _zoomControl:ZoomControl = new ZoomControl();
			var _mapTypeControl:ViewControl = new ViewControl();
			
			build.buildMap.addControl(_zoomControl);
			build.buildMap.addControl(_mapTypeControl);
			
			var lo:LineOverlay = new LineOverlay();
			var shapes:PointLLCollection = new PointLLCollection();	
			lo.setShapePoints(shapes);	
			build.buildMap.addOverlay(lo);

			build.buildMap.setCenter(new PointLL(43.0683060, -88.2603338));

            build.addEventListener(ResizeEvent.RESIZE, handleContainerResize); 
            build.buildMap.addEventListener(TileMapEvent.CLICK, mapClick );
            build.buildMap.addEventListener(MouseEvent.MOUSE_OVER, changeCursor );
            build.buildMap.addEventListener(MouseEvent.MOUSE_OUT, removeCursor );
            build.buildMap.addEventListener( TileMapEvent.ZOOM_END, zoomNotice );
            build.buildMap.addShapeCollection(wpCollection);

		}
		
		private function mMove(event:MouseEvent):void {
			if( event.buttonDown == false) {
				dragging = false;
			}
		}
		
		private function dragStart(event:MouseEvent):void {
            //activeCursor = build.buildMap.cursorManager.setCursor(wpCursor,1);
            trace("Drag Start");
            dragging = true;
		}
		
		private function dragEnd(event:MouseEvent):void {
            //activeCursor = build.buildMap.cursorManager.setCursor(wpCursor,1);
            trace("Drag End");
		}
		
		
		private function changeCursor(event:MouseEvent):void {
            //activeCursor = build.buildMap.cursorManager.setCursor(wpCursor,1);
		}
		
		private function removeCursor(event:MouseEvent):void {
            //build.buildMap.cursorManager.removeCursor(activeCursor);
		}
        private function handleContainerResize(event:ResizeEvent):void {
            // set the size of the map based on its containers size.
            //_mqMap.setSize(new Size(map.mapContainer.width,map.mapContainer.height)); 
            //build.buildMap.setSize(new Size(build.width,build.height));
        }
        
        private function mapClick(event:TileMapEvent):void {

			if( routing ) {
	        	if( !dragging ) {
		        	var collection:ShapeCollection = build.buildMap.getShapeCollection("waypoints");
		        	// Create a POI object and set it's location.
		        	var xyPoint:IPointXY = event.xy;
		        	var llPoint:IPointLL = build.buildMap.pixToLL(xyPoint);
					var waypoint:Poi = new Poi(llPoint);
		         	
					var icon:MapIcon = new MapIcon();
					icon.setImage(new wpIcon(),19,28);
					var offset:PointXY = new PointXY(-3, -23);
					icon.setAnchorOffset(offset);			// Associate icon with POI
					waypoint.setIcon(icon);
					waypoint.setDraggable(true);
					waypoint.setKey(wpIndex.toString());
					waypoint.setInfoTitle(waypoint.getKey());
					waypoint.addEventListener(MouseEvent.MOUSE_DOWN, dragStart );
					collection.add(waypoint);
					wpIndex++;		
	        	}
	        	else {
	        		dragging = false;
	        	}
	        	calculateRoute();
	  		}
        }
        
        private function enableRouting(event:Event=null):void {
        	routing = true;
        }
        
        private function clearRoute(event:Event=null):void {
        	var collection:ShapeCollection = build.buildMap.getShapeCollection("waypoints");
        	collection.removeAll();
        	wpIndex = 0;
        	var locCollection:LocationCollection = new LocationCollection();
        	exec.doRoute(locCollection, new RouteOptions(),sessionId);
		}
        
        private function calculateRoute():void {
        	var collection:ShapeCollection = build.buildMap.getShapeCollection("waypoints");
        	if( collection.length > 1 ) {
        	
	        	var locCollection:LocationCollection = new LocationCollection();
	        	var ctr:int;
	        	for( ctr = 0; ctr < collection.length; ctr++ ) {
	        		var shape:Poi = collection.get(ctr) as Poi;
	        		var place:GeoAddress = new GeoAddress();
	        		place.setLatLng( new LatLng(shape.getLatLng().lat,shape.getLatLng().lng));
	        		locCollection.add(place);
	        	}
	        	exec.doRoute(locCollection, new RouteOptions(),sessionId);
	        }
        }
        
        private function routeResults(evt:ExecResultEvent):void {

        	var rr:RouteResults = RouteResults(evt.resultData) as RouteResults;     	
        	build.buildMap.addRouteHighlight(rr.getBoundingBox(), "http://map.dev.mapquest.com",this.sessionId,false);

        }
        
        private function routeError(event:ExecFaultEvent):void {
        	
        }
        
		private function mapPoints(points:ArrayCollection, lineData:ArrayCollection) :void {
			var idx:Number = 0;
			var len:Number = points.length;
			
			var lo:LineOverlay = new LineOverlay();
			var shapes:PointLLCollection = new PointLLCollection();
			var icons:ShapeCollection = new ShapeCollection("icons");
			var shapesArray:Array = new Array();
			// Embed the Icon in the Class
			[Embed (source="/images/orSquare.png")]
			var NyIcon:Class;
			
			try {
				build.buildMap.removeAllOverlays();
				build.buildMap.removeAllShapes();
				clearRoute(null);
			}
			catch( ex:Error ) {
				// Do nothing
			}
            for (idx = 0; idx < len; idx++) {
            	var pt:CourseDataVO = points.getItemAt(idx) as CourseDataVO;
            	var ld:LineDataVO = lineData.getItemAt(idx) as LineDataVO;
            	var shape:PointLL = new PointLL(pt.latitude, pt.longitude);
             	shapes.addPointLL(shape);
             	shapesArray.push(shape);
             	
             	// Create a POI object and set it's location.
				var _myPoi:Poi = new Poi(shape);
             	
				// Set rollover and popup text.
				_myPoi.setInfoTitle("Slope: " + ld.slope.toString());
				//_myPoi.setInfoContent("Slope: " + pt.slope.toString());
				// A key value can be assigned to help you keep track of the poi's you put on the map.
				_myPoi.setKey("A" + idx.toString());
				// Create new icon object
				var _myIcon:MapIcon = new MapIcon();
				_myIcon.setImage(new NyIcon(),5,5);
				// Associate icon with POI
				_myPoi.setIcon(_myIcon);
				_myPoi.setMinZoomLevel(11);
				_myPoi.setMaxZoomLevel(16);
				// Add the Poi to the map.
				build.buildMap.addShape(_myPoi);			
							
             }
            
            lo.setBorderWidth(10);
            lo.setColor(0xFF0000);
            lo.setColorAlpha(0.4);
            lo.setShapePoints(shapes);
            //lo.addEventListener(MouseEvent.MOUSE_OVER, this.processRollover );
            //lo.addEventListener(MouseEvent.MOUSE_OUT, this.processRollout );
            build.buildMap.addOverlay(lo);
            build.buildMap.bestFitLL(shapesArray);
            
		}
		
		public function zoomNotice( te:TileMapEvent ):void {
			
			trace(te.zoom);
			
		}		
		        
	}
}